/**************************************************************************//**
 * @item     CosyOS-III Config
 * @file     mcucfg_8051.h
 * @brief    8051 Core Config File
 * @author   迟凯峰
 * @version  V2.0.1
 * @date     2025.08.19
 ******************************************************************************/

#ifndef __MCUCFG_8051_H
#define __MCUCFG_8051_H

///////////////////////////////////////////////////////////////////////////////

          //*** <<< Use Configuration Wizard in Context Menu >>> ***//

///////////////////////////////////////////////////////////////////////////////
// <o> 系统时钟频率
// <i> 告知CosyOS您所配置的系统时钟，单位即可为赫兹（HZ）也可为兆赫（MHZ），需输入整数。
// <i> 例如系统时钟为24MHZ，您即可输入24000000，也可输入24。
// <i> 如果系统时钟为11.0592MHZ，仅能输入11059200。
#define __MCUCFG_SYSCLK                 24

///////////////////////////////////////////////////////////////////////////////
// <o> 任务队列内存
// <1=> data <2=> xdata
// <i> 任务队列内存，会对任务调度性能产生显著影响，建议尽量配置在DATA中。
#define __MCUCFG_MEMORY_TASKQUE         2

///////////////////////////////////////////////////////////////////////////////
// <h> REGBANK配置
// <i> REGBANK配置

// <o> REGBANK-任务
// <0=> bank0 <1=> bank1 <2=> bank2 <3=> bank3
// <i> 告知CosyOS，任务使用哪一个REGBANK？
// <i> 在默认情况下，如果您未做出特别的调整，所有任务都将使用bank0。
#define MCUCFG_TASK_REGBANK             0

// <o> REGBANK-系统中断
// <0=> bank0 <1=> bank1 <2=> bank2 <3=> bank3
// <i> 配置系统中断所使用的REGBANK。
// <i> 如果系统中断被配置为使用独立的REGBANK（与任务使用不同的REGBANK），任务切换性能将显著提升。
#define MCUCFG_OSIT_REGBANK             0

// </h>
///////////////////////////////////////////////////////////////////////////////
// <h> PendSV中断配置
// <i> 您可选择一个未使用的硬件中断，做为PendSV软中断，用于执行系统的挂起服务。
// <i> 还需在初始化钩子中配置该中断，确保它不会被硬件触发，中断优先级必须为最低级。

// <o> 中断向量地址
// <i> 中断向量地址
#define MCUCFG_PENDSV_VECTORADDR        0003H

// <o> 中断开启
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：EX0 = 1
#define mPendSV_Enable()                EX0 = 1

// <o> 中断关闭
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：EX0 = 0
#define mPendSV_Disable()               EX0 = 0

// <o> 中断触发（置中断标志位）
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例：IE0 = 1
#define mPendSV_Set()                   IE0 = 1

// <o> 中断清零（清中断标志位）
// <i> 此项您应在文本编辑界面中定义，必须使用汇编代码。
// <i> 即使该标志位能够在中断服务程序中硬件自动清零，仍建议用户不要省略，以确保其可靠清零。
// <i> 示例：CLR IE0
#define mPendSV_Clear                   CLR IE0

// </h>
///////////////////////////////////////////////////////////////////////////////
// <o> PendSV_FIFO深度
// <0=> 0级（不启用PendSV_FIFO）<8=> 8级 <16=> 16级 <24=> 24级 <32=> 32级 <40=> 40级
// <i> 此项参数取决于您在中断中调用挂起服务的总数及中断的频率。
// <i> 对于8051来说，PendSV_FIFO的最大深度为40，您应妥善处理中断中调用的挂起服务，避免不必要的调用。
// <i> 可开启PendSV_FIFO监控功能，监控历史上的最大值，再适当增大，以确保其不会溢出。
#define MCUCFG_PENDSVFIFO_DEPTH         16

///////////////////////////////////////////////////////////////////////////////
// <h> 动态内存设置
// <i> CosyOS会使用下列参数自动初始化内存池。

// <o> 内存池指针
// <i> 内存池的起始内存地址
#define MCUCFG_MALLOCMEMBPTR            5632

// <o> 内存池大小（Bytes）
// <i> 内存池大小，单位为字节数
#define MCUCFG_MALLOCMEMSIZE            2048

// </h>
///////////////////////////////////////////////////////////////////////////////
// <o> 虚拟中断技术
// <i> 虚拟中断就是把任务虚拟成中断，这样C51编译器就会认为任务是中断了，所有任务都将自动成为调用树覆盖分析的根。
// <i> 当启用虚拟中断技术时，您需在此配置一个中断向量号（非零值且硬件中断未使用）。
// <i> 当启用虚拟中断技术时，会同时引发告警 L5/L30，当确定硬件中断不会引发该告警时，
// <i> 可自行屏蔽该告警在 BL51 Misc/LX51 Misc 标签页。
// <i> 取值范围：
// <i> BL51 && 使能中断向量号拓展：<0-254>
// <i> LX51 || 未能中断向量号拓展：<0- 31>
// <i> 其中0为不启用虚拟中断技术。
#define MCUCFG_TASK_VECTOR              0

///////////////////////////////////////////////////////////////////////////////
// <q> 系统变量零安装
// <i> 部分系统变量需要初始化为0，否则系统可能会运行异常，这些变量可能存储在任何物理内存区域；
// <i> 如果未能在启动文件中正确配置全部内存清零，应开启该选项，系统在定义变量时会自动赋值为0。
#define MCUCFG_OSZEROINSTALL            1

///////////////////////////////////////////////////////////////////////////////
// <h> 任务切换现场保护
// <i> 任务切换现场保护

// <q> XBPSTACK
// <i> 是否启用大模型可重入栈的任务切换现场保护？
// <i> 如果启用该功能，当任务切换恢复现场时，会存在关闭总中断EA的行为；
// <i> 编译器在对可重入栈指针的相关访问中，也会存在关闭总中断EA的行为；
// <i> 这将会导致非零中断延迟，用户应知晓。
#define MCUCFG_XBPSTACK                 0

// <h> 用户自定义
// <i> CosyOS在任务切换时，默认自动保存的寄存器：{PC,A,B,DPH,DPL,PSW,TASK-REGBANK:R0-R7,[?C_XBP]}。
// <i> 如您需要额外增加对其它寄存器的现场保护，可配置下面的选项。
// <i> 您可选择用C语言或汇编语言来写现场保护的代码，应用非常灵活。

// <q> C语言保护方案
// <i> 是否启用C语言保护方案？
// <i> 下方各定义项已经直接给出示例（保护/恢复：DPH1、DPL1、DPS），直接在文本编辑界面中修改即可。
#define __MCUCFG_USERREGSAVE_C          0

#if (__MCUCFG_USERREGSAVE_C == 1)

// 定义用于现场保护的数组
// 定义一个"unsigned char"类型的数组，结尾必须加语句结束符";"。
#define mUserReg_DEFc_ \
	unsigned char user_reg[3];

// 定义保护现场代码
// 用c语言代码，将相应寄存器的内容拷贝至自定义的数组中。
#define mUserReg_SAVEc() \
do{ \
	s_task_current->user_reg[0] = DPH1; \
	s_task_current->user_reg[1] = DPL1; \
	s_task_current->user_reg[2] = DPS; \
}while(false)

// 定义恢复现场代码
// 用c语言代码，将自定义数组中的数据恢复至相应的寄存器。
#define mUserReg_RESc() \
do{ \
	DPH1  = node_news->user_reg[0]; \
	DPL1  = node_news->user_reg[1]; \
	DPS   = node_news->user_reg[2]; \
}while(false)

// 寄存器数据初始化
// 用c语言代码，初始化自定义数组中的寄存器数据。
#define mUserReg_INITc() \
do{ \
	node_news->user_reg[0] = DPH1; \
	node_news->user_reg[1] = DPL1; \
	node_news->user_reg[2] = DPS; \
}while(false)

#endif

// <e> 汇编语言保护方案
// <i> 是否启用汇编语言保护方案？
// <i> 需先配置下面的选项，而后在 mcucfg_8051.inc 文件中写代码。
#define __MCUCFG_USERREGSAVE_ASM        0

#if (__MCUCFG_USERREGSAVE_ASM == 1)

// <o> 用户寄存器SIZE
// <i> 定义现场保护的用户寄存器的总字节数。
#define MCUCFG_USERREGSIZE              3

// <o> 保护方案选择
// <1=> 保护方案一 <2=> 保护方案二
// <i> 保护方案一：采用PUSH/POP指令入栈/出栈，操作简单、代码简洁、但性能偏低。
// <i> 保护方案二：在用户寄存器与任务栈之间直接搬移数据，操作相对繁琐，代码量稍大，但性能高效。
#define MCUCFG_USERREGCONFIG            2

// 寄存器数据初始化
// 用c语言代码，初始化任务栈中的寄存器数据。
#define mUserReg_INITa() \
do{ \
	*(s_u8_t *)(mUserReg_Addr + 0) = DPH1; \
	*(s_u8_t *)(mUserReg_Addr + 1) = DPL1; \
	*(s_u8_t *)(mUserReg_Addr + 2) = DPS; \
}while(false)

#endif
// </e>
// </h>
// </h>
///////////////////////////////////////////////////////////////////////////////

                //*** <<< end of configuration section >>> ***//

///////////////////////////////////////////////////////////////////////////////

#if   (__MCUCFG_SYSCLK && __MCUCFG_SYSCLK <= 255)
#define MCUCFG_SYSCLK   (__MCUCFG_SYSCLK / 1UL)
#define MCUCFG_SYSCLKHZ (__MCUCFG_SYSCLK * 1000000UL)
#elif (__MCUCFG_SYSCLK >= 1000000UL)
#define MCUCFG_SYSCLK   (__MCUCFG_SYSCLK / 1000000UL)
#define MCUCFG_SYSCLKHZ (__MCUCFG_SYSCLK * 1UL)
#else
#error 参数非法 of 系统时钟！
#endif

#if (__MCUCFG_MEMORY_TASKQUE == 1)
#define _QUE_MEM_ data
#else
#define _QUE_MEM_ xdata
#endif

#if (!__MCUCFG_USERREGSAVE_C)
#define mUserReg_DEFc_
#define mUserReg_SAVEc()
#define mUserReg_RESc()
#define mUserReg_INITc()
#endif

#if (!__MCUCFG_USERREGSAVE_ASM)
#define MCUCFG_USERREGSIZE   0
#define MCUCFG_USERREGCONFIG 0
#define mUserReg_INITa()
#else
#if (MCUCFG_USERREGCONFIG == 1)
#define mUserReg_Addr (node_news->bsp + (MCUCFG_TASK_REGBANK == MCUCFG_OSIT_REGBANK ? 15 : 7))
#else
#define mUserReg_Addr (node_news->bsp + 15)
#endif
#endif

#if ((MCUCFG_PENDSVFIFO_DEPTH % 8) || (MCUCFG_PENDSVFIFO_DEPTH > 40))
#error 参数非法 of 中断挂起服务FIFO队列深度！
#endif



#endif
